grammar gmini;

options 
{
	backtrack = true;
	language = C;
	//charVocabulary = '\3'..'\377';
	//testLiteral = true;
}

@parser::includes
{
	#include "parserHelper.h"
	#include "gminiGraph.h"
}


/**
* \brief Denotes a lexical  identifier to be used for variable names in parser
*/

ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

/**
* \brief Denotes an lexiccal identifier of an arithmetic integer
*/
INT : ('0' | '1'..'9' '0'..'9'*)
	;
		
/**
* \brief Denotes an lexiccal identifier of a comment
* \note comments are ignored when parsing
*/
COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

/**
* \brief Denotes an lexiccal identifier of a whitespace 
* \note includes also tabs and endlines
*/
WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

/**
* \brief Denotes an parser rule which identifies the different arithmetic operators such as +,-/,%
* \return op: string containing the symbol of the operator 
*/
arithmeticOperator returns [char* op ]
	: ope = ('*' | '/' | '^' | '+' | '-' | '%') 
	{ op = (char*)$ope.text->chars; }
	;

/**
* \brief Denotes a parser rule for any type of expresion that evaluates to an integer or is a constant integer itself. 
* \description It may contain arithmetic operators where paranthesization is enforced. 
*   	       In addition, any variable, valid entry of an Array or a Pair which evaluates to an integer is an acceptable building block of the expression
* \return node: the root of the sub-tree which corresponds to the Expression, where each operator, variable, 
*		or constant corresponds to a single node in the returned tree 
*/
arithmeticExp returns [Node * node]
	@init{out("arith");}
	:   ( 	'(' a1 = arithmeticExp operator1 = arithmeticOperator a2 = arithmeticExp ')'
		{
			node = new Node(ARITH_OP, (string)$operator1.op);
	 		parsingGraph.createEdge(node, $a1.node,LEFT);
	 		parsingGraph.createEdge(node, $a2.node,RIGHT);
		}
	    )
	|  (	
		p=pAIRoperator[TypeList(1,t_INT)]
		{
			node=$p.node;
		}
	   )
	|  (	
		p=aRRAYoperator[TypeList(1,t_INT)]
		{
			node=$p.node;
		}
	   )
	| 	ID 
		{	
			if (checkBasicVariable($ID,t_INT))
				node =new Node(ID_NAME,(string)((char*)$ID.text->chars));
			else
				node =new Node(ERROR_NODE,"Incompatible Types");
		} 
	| 	INT 
		{
			node =new Node(INT_VAL,(string)((char*)$INT.text->chars));
		}
	;

/**
* \brief Denotes a parser rule for an Arithmetic Expression in which outer paranthesization is not expected or enforced. 
* \note Still, other than the outside paranthesis, all others are required when a complex expression is needed
* \return node: the root of the sub-tree which corresponds to the Expression.
*/
arithmeticExpNoPara returns [Node * node]
	: ( 	a1 = arithmeticExp operator1 = arithmeticOperator a2 = arithmeticExp  
		{
			node = new Node(ARITH_OP, (string)$operator1.op);
			parsingGraph.createEdge(node, $a1.node,LEFT);
			parsingGraph.createEdge(node, $a2.node,RIGHT);
		}
	   )	
	|	INT 
		{
			node =new Node(INT_VAL,(string)((char*)$INT.text->chars));
		}
	|  (	ID 	
		{
			getBasicType((string)(char*)$ID.text->chars,0)==t_INT
		}?
	   
		{ 
			node =new Node(ID_NAME,(string)((char*)$ID.text->chars));
		}
	   )
	|  (	
		p=pAIRoperator[TypeList(1,t_INT)]
		{
			node=$p.node;
		}
	   )
	|  (	
		p=aRRAYoperator[TypeList(1,t_INT)]
		{
			node=$p.node;
		}
	   )
	;
	
/**
* \brief Denotes a parser rule which identifies a constant boolean (i.e. 'true' or 'false') 
* \return val: the text of the constant.
*/
bOOLConstant returns [char* val]
	: 	c=('true'| 'false')
		{
			val=(char*)$c.text->chars;
		}
	;

/**
* \brief Denotes an parser rule which identifies the different boolean comparators such as '<=', '>', '!='
* \return val: string containing the symbol of the comparator 
*/
bOOLcomp returns [char * val]
	: 	c=('<=' | '>=' |'<' | '>' | '==' | '!=') 
		{
			val=(char*)$c.text->chars;
		}
	;

/**
* \brief Denotes an parser rule which identifies the different boolean operators such as '&&', '||', '=>'
* \note '<>' corresponding to XOR
* \return op: string containing the symbol of the comparator 
*/
bOOLops	returns [char * op]
	:	c=('&&'| '||' | '=>'  | '<=>'  | '<>')//<> is XOR
		{
			op=(char*)$c.text->chars;
		}
	;

/**
* \brief Denotes a parser rule for any type of expresion that evaluates to a boolean or is a constant boolean itself. 
* \description It may contain boolean operators where paranthesization is enforced. Also comparators of 2 arithmetic expressions evaluates into a boolean
*   	       In addition, any variable, valid entry of an Array or a Pair which evaluates to a boolean is an acceptable building block of the expression
* \return node: the root of the sub-tree which corresponds to the Expression, where each operator, variable, comparator 
		or constant corresponds to a single node in the returned tree 
*/
bOOLExp returns [Node * node]
	:  (	
		'('e1=bOOLExp o=bOOLops e2=bOOLExp ')'
		{
			 node=new Node(BOOL_OP, (string)$o.op);
			 parsingGraph.createEdge(node, $e1.node,LEFT);
			 parsingGraph.createEdge(node, $e2.node,RIGHT);
		}
	   )
	|  (
		'(' a1=arithmeticExp b=bOOLcomp a2=arithmeticExp ')'
		{
			node=new Node(BOOL_COMP, (string)$b.val);
			parsingGraph.createEdge(node, $a1.node,LEFT);
			parsingGraph.createEdge(node, $a2.node,RIGHT);
		}
	   )
	|  (
		'!' e=bOOLExp
		{ 
		  	node =new Node(BOOL_OP,"!");
		    	parsingGraph.createEdge(node, $e.node,OF_EDGE);
		}
	   )
	|  (	
		ID  
	  	{
	  		if (checkBasicVariable($ID,t_BOOL))
				node = new Node(ID_NAME,(string)((char*)$ID.text->chars));
			else
				node =new Node(ERROR_NODE,"Incompatible Types");
		}
	   )
	|  (
		b=bOOLConstant
	  	{
	  		node = new Node(BOOL_VAL,(string)$b.val);
	  	}
	   )
	|  (	
		p=pAIRoperator[TypeList(1,t_BOOL)]
		{
			node=$p.node;
		}
	   )
	|  (	
		p=aRRAYoperator[TypeList(1,t_BOOL)]
		{
			node=$p.node;
		}
	   )
	|  (
		(~('\n'|'\r'|';'))*
		{
			cout<<"Incompatible type with BOOL"<<endl;
			node =new Node(ERROR_NODE,"Incompatible Types");
		}
	   )
	;

/**
* \brief Denotes a parser rule for an Boolean Expression in which outer paranthesization is not expected or enforced. 
* \note Still, other than the outside paranthesis, all others are required when a complex expression is needed
* \return node: the root of the sub-tree which corresponds to the Expression.
*/
bOOLExpNoPara returns [Node * node]
	: ( 	
		a1=arithmeticExp b=bOOLcomp a2=arithmeticExp 
		{
			node=new Node(BOOL_COMP, (string)$b.val);
			parsingGraph.createEdge(node, $a1.node,LEFT);
			parsingGraph.createEdge(node, $a2.node,RIGHT);
		}
	  )
	| (
		e1=bOOLExp o=bOOLops e2=bOOLExp 
		{
			node=new Node(BOOL_OP, (string)$o.op);
			parsingGraph.createEdge(node, $e1.node,LEFT);
			parsingGraph.createEdge(node, $e2.node,RIGHT);
		}
	  )
	| (
		'!' (e=bOOLExp)
		 {
		 	node =new Node(BOOL_OP,"!");
			parsingGraph.createEdge(node, $e.node,OF_EDGE);
		 }
	  )
	| (
		ID  
	  	{
		  	if (checkBasicVariable($ID,t_BOOL))
		   		node = new Node(ID_NAME,(string)((char*)$ID.text->chars));
		   	else
				node =new Node(ERROR_NODE,"Incompatible Types");
		}
	  )
	| (
		b=bOOLConstant
	  	{
	  		node = new Node(BOOL_VAL,(string)$b.val);
	  	}
	  )
	| (	
		p=pAIRoperator[TypeList(1,t_BOOL)]
		{
			node=$p.node;
		}
	  )
	| (	
		p=aRRAYoperator[TypeList(1,t_BOOL)]
		{
			node=$p.node;
		}
	  )
	;	

/**
* \brief Denotes a parser rule for an integer declaration statement.
* 
* The only acceptable form of the statement is 'int x', where x denotes the name of the variable.
*
* \note When declaring a variable, it cannot be initialized. Initialization must take place in a seperate assignment statement
* \return node: the root of the sub-tree which corresponds to the statement.
*/
iNTdeclarartionstatement returns [Node * node]	
	: (	
		i ='int'  id = ID 
		{
			appendType(t_INT);
			storeVariable((string)(char*)($ID.text->chars));
			node =new Node(DECL,"Int Declaration");	
			Node * int_dec= new Node (INT_TYPE, (string)((char*)$i.text->chars));
			Node * ID_name= new Node (ID_NAME, (string)((char*)$id.text->chars));
			parsingGraph.createEdge(node, int_dec,VARTYPE);
			parsingGraph.createEdge(node, ID_name,VARNAME);
		}
	  )
	// | ('int'  ID '=' (arithmeticExp))
	;

/**
* \brief Denotes a parser rule for an boolean declaration statement.
* 
* The only acceptable form of the statement is 'bool x', where x denotes the name of the variable.
*
* \note When declaring a variable, it cannot be initialized. Initialization must take place in a seperate assignment statement
* \return node: the root of the sub-tree which corresponds to the statement.
*/
bOOLdeclarartionstatement returns [Node * node]
	:  (
		i='bool' id=ID 
		{
			appendType(t_BOOL);
			storeVariable((string)(char*)($ID.text->chars));			
			node =new Node(DECL,"Bool Declaration");	
			Node * bool_dec= new Node (BOOL_TYPE, (string)((char*)$i.text->chars));
			Node * ID_name= new Node (ID_NAME, (string)((char*)$id.text->chars));
			parsingGraph.createEdge(node, bool_dec,VARTYPE);
			parsingGraph.createEdge(node, ID_name,VARNAME);		
		}
	    )
	// | ('bool' ID '=' (bOOLExp))
	;

/**
* \brief Denotes a parser rule for a variable type.
* 
* The types can be basic or composite. Basic types are 'bool' and 'int'; while composite types are Arrays of some type, or a Pair of  
* two other types. When the type is basic, it is represented by a single node; while composite types are represented by a corresponding tree
*
* \return node: the root of the sub-tree which corresponds to the Variable Type.
*/
type	returns [Node * node]
	: (
		'bool' 
		{
			appendType(t_BOOL); 
			node = new Node(BOOL_TYPE,"bool");
		}
	  ) 
	| (
		'int'  
		{
			appendType(t_INT);
			node = new Node(INT_TYPE,"int");
		}
	  )
	| (
		n=aRRAYtype 
		{
			node=$n.node;
		}
	  ) 
	| (
		n=pAIRtype
		{
			node=$n.node;
		}
	  )
	;

/**
* \brief Denotes a parser rule for a Pair type.
* 
* An example of a valid type: Pair<int, Array<bool> >
*
* \return node: the root of the sub-tree which corresponds to the Variable Type.
*/
pAIRtype returns [Node * node]
	: (
		'Pair'
		{
			appendType(t_PAIR);
		} 
		'<' t1=type ',' t2=type '>' 
		{ 
			node = new Node(PAIR_TYPE,"pair");
			parsingGraph.createEdge(node,$t1.node,LEFT);
			parsingGraph.createEdge(node,$t2.node,RIGHT);
		}
	   )
	;

/**
* \brief Denotes a parser rule for an Array type.
* 
* An example of a valid type: Array<int>
*
* \return node: the root of the sub-tree which corresponds to the Variable Type.
*/
aRRAYtype returns [Node * node]
	: (
		'Array'
		{
			appendType(t_ARRAY);
		} 
		'<' t=type '>' 
		{
			node = new Node(ARRAY_TYPE,"array");
			parsingGraph.createEdge(node,$t.node,OF_EDGE);
		}
	   )
	;

/**
* \brief Denotes a parser rule for an Pair declaration statement.
* \note When declaring a variable, it cannot be initialized. Initialization must take place in a seperate assignment statement
* \return node: the root of the sub-tree which corresponds to the statement.
*/	
pAIRdeclarationstatement returns [Node * node]
	: (
		t=pAIRtype ID
		{
			storeVariable((string)(char*)($ID.text->chars));
			node =new Node(DECL,"Pair Declaration");	
			Node * ID_name= new Node (ID_NAME, (string)((char*)$ID.text->chars));
			parsingGraph.createEdge(node, $t.node,VARTYPE);
			parsingGraph.createEdge(node, ID_name,VARNAME);
		}
	   )
	;

/**
* \brief Denotes a parser rule for an Array declaration statement.
* \note When declaring a variable, it cannot be initialized. Initialization must take place in a seperate assignment statement
* \return node: the root of the sub-tree which corresponds to the statement.
*/		
aRRAYdeclarationstatement returns [Node * node]
	: (
		t=aRRAYtype  ID'(' size=arithmeticExp ')'
		{
			storeVariable((string)(char*)($ID.text->chars));
			node =new Node(DECL,"Array Declaration");	
			Node * ID_name= new Node (ID_NAME, (string)((char*)$ID.text->chars));
			parsingGraph.createEdge(node, $t.node,VARTYPE);
			parsingGraph.createEdge(node, ID_name,VARNAME);
			parsingGraph.createEdge(node, $size.node,ARRAYSIZE);
		}
	  )
	;

/**
* \brief Denotes a parser rule for any of the 4 types of declaration statements.
* \note When declaring a variable, it cannot be initialized. Initialization must take place in a seperate assignment statement
* \return node: the root of the sub-tree which corresponds to the statement.
*/	
declarationStatement returns [Node * node]
	: (d=aRRAYdeclarationstatement {node=$d.node;}) 
	| (d=pAIRdeclarationstatement  {node=$d.node;}) 
	| (d=bOOLdeclarartionstatement {node=$d.node;})
	| (d=iNTdeclarartionstatement  {node=$d.node;})
	;

/**
* \brief Denotes a parser rule for an assignment statement where an arithmetic expression is assigned to an integer variable
* \return node: the root of the sub-tree which corresponds to the statement.
*/
arithAssignmentStatement returns [Node * node]
	:  (
		id = ID 
		{
			getBasicType((string)(char*)$ID.text->chars,0)==t_INT
		}?
	   	'=' arith = arithmeticExp
		{
		 	node =new Node(ASSIGN_ST,"Arith Assignment");	
			Node * ID_name= new Node (ID_NAME, (string)((char*)$id.text->chars));
			parsingGraph.createEdge(node, ID_name,LEFT);
			parsingGraph.createEdge(node, $arith.node,RIGHT);
		}
	   )	
	;

/**
* \brief Denotes a parser rule for an assignment statement where a boolean expression is assigned to a boolean variable
* \return node: the root of the sub-tree which corresponds to the statement.
*/	
bOOLassignmentStatement returns [Node * node]
	:  ( 
		id = ID 
		{
			getBasicType((string)(char*)$ID.text->chars,0)==t_BOOL
		}?
		'=' exp = bOOLExp	
		{
			node =new Node(ASSIGN_ST,"Bool Assignment");	
			Node * ID_name= new Node (ID_NAME, (string)((char*)$id.text->chars));
			parsingGraph.createEdge(node, ID_name,LEFT);
			parsingGraph.createEdge(node, $exp.node,RIGHT);
		}
	    )
	;

aRRAYoperator[TypeList t] returns [Node *node]
	:   (
		b=ID '[' in = arithmeticExpNoPara ']' 
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_ARRAY 
			&& getRemainingType((string)(char*)$b.text->chars,1)==t
		}?
		{
			node =new Node(ARRAY_OP,"[]");
			parsingGraph.createEdge(node, $in.node,INDEX);
			Node * arrayname= new Node (ID_NAME, (string)((char*)$b.text->chars));
			parsingGraph.createEdge(node, arrayname,VARNAME);
		}
	    )
	;
	
pAIRoperator[TypeList t] returns [Node *node]
	 :  (
		b=ID '('in = INT')'
		{ 
			getBasicType( (string)(char*)$b.text->chars, 0)==t_PAIR 
			 && ( getRemainingType(	(string)(char*)$b.text->chars,getInt($INT))==t)
			 || !(getInt($INT)==0 || getInt($INT)==1)
		}?
		{//Note I changed here to an if-else structure
			if (!checkPairIndex($b, (string)((char*)$INT.text->chars)))
			{
		 		node =new Node(ERROR_NODE,"Invalid Pair Index");
		 	}
		 	else
		 	{
				node =new Node(PAIR_OP,"( )");
				Node * intval= new Node (INT_VAL, (string)((char*)$in.text->chars));
				parsingGraph.createEdge(node, intval,INDEX);
				Node * arrayname= new Node (ID_NAME, (string)((char*)$b.text->chars));
				parsingGraph.createEdge(node, arrayname,VARNAME);
		 	}
		}
	   )
	;

/**
* \brief Denotes a parser rule for an array assignment statement where an element of an array is assigned to another variable of incompatible type or vise versa
* \note This rule is provided to be able to overide the default Antr errors with more expressive ones.
* \return node: an error node along with the description of the error
*/
wrong_aRRAYoperatorsStatement returns [Node *node]
	:  (
		b=ID '[' arithmeticExpNoPara ']' '=' a=ID 
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_ARRAY 
			&& getRemainingType((string)(char*)$b.text->chars,1)!=getCompositeType((string)(char*)$a.text->chars)
		}? 
		{
			errorMessage($b,"Incompatible Types for " + (string)(char*)$b.text->chars+ "[] Array Element with " +(string)(char*)$a.text->chars);
			node =new Node(ERROR_NODE,"Incompatible Types");
		}
	   )
	|  (
		a=ID '=' b=ID 
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_ARRAY 
			&& getRemainingType((string)(char*)$b.text->chars,1)!=getCompositeType((string)(char*)$a.text->chars)
		}?
	   	'[' arithmeticExpNoPara ']'
	   	{
	   		errorMessage($b,"Incompatible Types for "+(string)(char*)$a.text->chars+" with Array Element " + (string)(char*)$b.text->chars+ "[]");
	   		node =new Node(ERROR_NODE,"Incompatible Types");
	   	}
	   )
	;

/**
* \brief Denotes a parser rule for an assignment statement where an individual element of an array variable is assigned to another variable of same type or vise versa
* \note To access an element of an array we use the array operator '[ ]'
* \return node: the root of the sub-tree which corresponds to the statement.
*/
aRRAYoperatorsStatement returns [Node * node] //Note: this is an assignment statement
	@init{out("array");}
	:  (
		b=ID '[' in = arithmeticExpNoPara ']' '=' a=ID 
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_ARRAY 
			&& getRemainingType((string)(char*)$b.text->chars,1)==getCompositeType((string)(char*)$a.text->chars)
		}?
		{
			node =new Node(ASSIGN_ST,"Array Element Assign");
			Node * idname= new Node (ID_NAME, (string)((char*)$a.text->chars));
			parsingGraph.createEdge(node, idname, RIGHT);
			
			Node * node2 =new Node(ARRAY_OP,"[ ]");
			parsingGraph.createEdge(node, node2, LEFT);
			parsingGraph.createEdge(node2, $in.node,INDEX);
			Node * arrayname= new Node (ID_NAME, (string)((char*)$b.text->chars));
			parsingGraph.createEdge(node2, arrayname,VARNAME);
		}
	    )
	|   (
		b1 = ID '[' in1 = arithmeticExpNoPara ']' '=' a1= arithmeticExp
		{
			getBasicType((string)(char*)$ID.text->chars,0)==t_ARRAY 
			&& getBasicType((string)(char*)$ID.text->chars,1)==t_INT
		}?
		{
			node =new Node(ASSIGN_ST,"Array Element Assign");
			parsingGraph.createEdge(node, $a1.node, RIGHT);
			
			Node * node2 =new Node(ARRAY_OP,"[ ]");	
			parsingGraph.createEdge(node, node2, LEFT); 
			parsingGraph.createEdge(node2, $in1.node,INDEX);
			Node * arrayname= new Node (ID_NAME, (string)((char*)$b1.text->chars));
			parsingGraph.createEdge(node2, arrayname,VARNAME);	
		}
	    )
	|   (
		a=ID '=' b=ID 
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_ARRAY 
			&& getRemainingType((string)(char*)$b.text->chars,1)==getCompositeType((string)(char*)$a.text->chars)
		}?
	   	'[' in = arithmeticExpNoPara ']'
	   	{
			node =new Node(ASSIGN_ST,"Array Element Assign");
			Node * name= new Node (ID_NAME, (string)((char*)$a.text->chars));
			parsingGraph.createEdge(node,name, LEFT);
			
			Node * node2 =new Node(ARRAY_OP,"[ ]");	 
			parsingGraph.createEdge(node, node2, RIGHT);
			parsingGraph.createEdge(node2, $in.node,INDEX);
			Node * arrayname= new Node (ID_NAME, (string)((char*)$b.text->chars));
			parsingGraph.createEdge(node2, arrayname,VARNAME);	
		}
	    )
	;

/**
* \brief Denotes a parser rule for an Pair assignment statement where one of the two element of a pair is assigned to another variable of incompatible type or vise versa
* \note This rule is provided to be able to overide the default Antr errors with more expressive ones.
* \return node: an error node along with the description of the error
*/
wrong_pAIRoperatorsStatement returns [Node * node]
	: (
		b=ID '('INT')' '='  a=ID
		{ 
			getBasicType((string)(char*)$b.text->chars,0)==t_PAIR 
		 	&& getRemainingType((string)(char*)$b.text->chars,getInt($INT))!=getCompositeType((string)(char*)$a.text->chars)
		}?
		{
			errorMessage($b,"Incompatible Types for " + (string)(char*)$b.text->chars+ "("+(string)(char*)$INT.text->chars +") Pair Element with " +(string)(char*)$a.text->chars);
		 	node =new Node(ERROR_NODE,"Incompatible Types");
		 }
	   )
	|  (
		a=ID '=' b=ID  '(' INT ')'
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_PAIR 
		 	&& getRemainingType((string)(char*)$b.text->chars,getInt($INT))!=getCompositeType((string)(char*)$a.text->chars)
		}?
	  	{
	  		errorMessage($b,"Incompatible Types for " +(string)(char*)$a.text->chars +" with "+ (string)(char*)$b.text->chars+ "("+(string)(char*)$INT.text->chars +") Pair Element");
		  	node =new Node(ERROR_NODE,"Incompatible Types");
		}
	   )	
	;

/**
* \brief Denotes a parser rule for an assignment statement where any of the two individual element of a pair variable are assigned to another variable of same type or vise versa
* \note To access an element of an array we use the pair operator '( )' which accepts only 1 or 2 as indicies
* \return node: the root of the sub-tree which corresponds to the statement.
*/
pAIRoperatorsStatement returns [Node * node] 	//Note: this is an assignment statement
						//p(1)=, p(2)=
	:  (
		b=ID '('in = INT')' '='  a=ID
		{ 
			getBasicType((string)(char*)$b.text->chars,0)==t_PAIR 
		 	&& (getRemainingType((string)(char*)$b.text->chars,getInt($INT))==getCompositeType((string)(char*)$a.text->chars)
		 	|| !(getInt($INT)==0 || getInt($INT)==1))
		}?
		{//Note I changed here to an if-else structure
			if (!checkPairIndex($a, (string)((char*)$INT.text->chars)))
			{
		 		node =new Node(ERROR_NODE,"Invalid Pair Index");
		 	}
		 	else
		 	{
				node =new Node(ASSIGN_ST,"Pair Element Assign");
				Node * idname= new Node (ID_NAME, (string)((char*)$a.text->chars));
				parsingGraph.createEdge(node, idname, RIGHT);
				
				Node * node2 =new Node(PAIR_OP,"( )");
				parsingGraph.createEdge(node, node2, LEFT);
				Node * intval= new Node (INT_VAL, (string)((char*)$in.text->chars));
				parsingGraph.createEdge(node2, intval,INDEX);
				Node * arrayname= new Node (ID_NAME, (string)((char*)$b.text->chars));
				parsingGraph.createEdge(node2, arrayname,VARNAME);
		 	}
		}
	   )
	|  (
		b1 = ID '('in1 = INT')' '='  a1 = arithmeticExp 
		{
			getBasicType((string)(char*)$ID.text->chars,0)==t_PAIR 
		 	&& (getBasicType((string)(char*)$ID.text->chars,getInt($INT))==t_INT
		 	|| !(getInt($INT)==0 || getInt($INT)==1))
		}?
		{
			if (!checkPairIndex($ID, (string)((char*)$INT.text->chars)))
				node =new Node(ERROR_NODE,"Invalid Pair Index");
			else
			{
				node =new Node(ASSIGN_ST,"Pair Element Assign");
				parsingGraph.createEdge(node, $a1.node, RIGHT);
				
				Node * node2 =new Node(PAIR_OP,"( )");	 
				parsingGraph.createEdge(node, node2, LEFT);
				Node * intval= new Node (INT_VAL, (string)((char*)$in1.text->chars));
				parsingGraph.createEdge(node2, intval,INDEX);
				
				Node * arrayname= new Node (ID_NAME, (string)((char*)$b1.text->chars));
				parsingGraph.createEdge(node2, arrayname,VARNAME);
			}	  
		}
	   )
	|  (
		a=ID '=' b=ID  '(' in = INT ')'
		{
			getBasicType((string)(char*)$b.text->chars,0)==t_PAIR 
		 	&& (getRemainingType((string)(char*)$b.text->chars,getInt($INT))==getCompositeType((string)(char*)$a.text->chars)
		 	|| !(getInt($INT)==0 || getInt($INT)==1))
		}?
	  	{
	  		if (!checkPairIndex($a, (string)((char*)$INT.text->chars)))
		  		node =new Node(ERROR_NODE,"Invalid Pair Index");
		  	else
		  	{ 
				node =new Node(ASSIGN_ST,"Pair Element Assign");
				Node * name= new Node (ID_NAME, (string)((char*)$a.text->chars));
				parsingGraph.createEdge(node,name, LEFT);
				
				Node * node2 =new Node(PAIR_OP,"()");	
				parsingGraph.createEdge(node, node2, RIGHT);
				Node * intval= new Node (INT_VAL, (string)((char*)$in.text->chars)); 
				parsingGraph.createEdge(node2, intval,INDEX);
				Node * arrayname= new Node (ID_NAME, (string)((char*)$b.text->chars));
				parsingGraph.createEdge(node2, arrayname,VARNAME);
			}
		}
	    )
	;

/**
* \brief Denotes a parser rule for any of the valid statements for gminii
* \return node: the root of the sub-tree which corresponds to the statement.
*/
statement  returns [Node * node]
	: (
		WS? ';'  
		{
			node =new Node(EMPTY_ST,"Empty Statement");
		}
	  )
	| (
		(
			s=declarationStatement {node=$s.node;}
		        | s=arithAssignmentStatement {node=$s.node;}
		        | s=aRRAYoperatorsStatement  {node=$s.node;}
		        | s=pAIRoperatorsStatement {node=$s.node;}
			| s=outputStatement {node=$s.node;}
			| s=bOOLassignmentStatement {node=$s.node;}
			| s=wrong_pAIRoperatorsStatement {node=$s.node;} 
			| s=wrong_aRRAYoperatorsStatement{node=$s.node;} 
		)
		(
			';' 
			| (
				{
					cout<<"Missing semicolon"<<endl;
					node =new Node(ERROR_NODE,"Missing semicolon");
				}
			   )
		)
	   )
	|  s=ifStatement {node=$s.node;}
	|  s=whileStatement {node=$s.node;}
	; 
 
/**
* \brief Denotes a parser rule for any group of consecutive valid statements for gmini.
* \note This is the the function that is called first to determine if a given code is of valid gmini syntax. 
* 	It is called by if and while statements also to check if their statement blocks are balid.
* \return node: the root of the sub-tree which corresponds to the first statement.
*/
statements returns [Node * node]
	@init{out("statements");}
	:  (
		s1=statement ('\n' | '\r\n')* 
		{
			static bool first_time=true;
			if (first_time)
			{
				node=new Node(START,"Start");
				parsingGraph.createEdge(node, $s1.node, NEXT_STATEMENT);
				first_time=false;
			}
			else
				node=$s1.node;
		}
		(
			s2=statements 
			{parsingGraph.createEdge($s1.node, $s2.node, NEXT_STATEMENT);}
		)?
	   )
	;

/**
* \brief Denotes a parser rule for an if statement
* \note gmini supports an optional else clause for the if statement.
* \return node: the root of the sub-tree which corresponds to the statement.
*/
ifStatement returns [Node * node]
    : 	'if' '('  (b = bOOLExpNoPara | b = bOOLExp) ')'
    	'\n'* '{' '\n'*
    	i = statements 
    	'}' '\n'* 
    	('else''\n'* '{''\n'* e = statements '}' )?
     	{
     		node = new Node(IF_ST, "If Statement");
    	 	parsingGraph.createEdge(node, $b.node,CONDITION);
    	  	parsingGraph.createEdge(node, $i.node,IF_STATEMENTS);
			parsingGraph.createEdge(node, $e.node,ELSE_STATEMENTS); //TODO: check why this does not cause a problem when e is not initialized in the case when there is no else-statement
    	}
    ;


/**
* \brief Denotes a parser rule for an while statement
* \return node: the root of the sub-tree which corresponds to the statement.
*/
whileStatement returns [Node * node]
    	:  (
	    	'while' '(' (b = bOOLExpNoPara | b = bOOLExp ) ')' 
	    	'\n'* '{' '\n'* 
	    	s= statements 
	    	'}'
	    	{
			node = new Node(WHILE_ST, "While Statement");
			parsingGraph.createEdge(node, $b.node,CONDITION);
			parsingGraph.createEdge(node, $s.node,WHILE_STATEMENTS);
	    	}
      	    )
	;

/**
* \brief Denotes a parser rule for an output statement which displays the content of an integer variable or an integer constant
* \return node: the root of the sub-tree which corresponds to the statement.
*/
outputStatement returns [Node * node]
 		: (
 			'output' '(' (exp = arithmeticExpNoPara ) ')' 
   			{
   				node = new Node(OUTPUT_ST, "Output Statement");
    	 		parsingGraph.createEdge(node, $exp.node,OF_EDGE);
    		}
    	  )
    	;

